<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>力导向图-表示节点之间的多对多的关系</title>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
</head>
<body>
    <script>
        //初始化SVG画布
        var width=1400;
        var height=600;
        var svg=d3.select('body').append('svg').attr('width',width).attr('height',height);
        //节点（nodes）
        var nodes = [ { name: "桂林" }, { name: "广州" },
                            { name: "厦门" }, { name: "杭州" },
                            { name: "上海" }, { name: "青岛" },
                            { name: "天津" } , { name: "西安" }];
        //连线（edges）
        var edges = [ { source : 0 , target: 1 } , { source : 0 , target: 2 } ,
                            { source : 0 , target: 3 } , { source : 1 , target: 4 } ,
                            { source : 1 , target: 5 } , { source : 1 , target: 6 } , 
                            { source : 1 , target: 7 } , { source : 0 , target: 7 }];
        //定义一个力导向图的布局                            
        var force = d3.layout.force()
                    .nodes(nodes) //指定节点数组
                    .links(edges) //指定连线数组
                    .size([width,height]) //指定作用域范围
                    .linkDistance(250) //指定连线长度
                    .charge([-400]); //相互之间的作用力
        //使力学作用生效
        force.start(); 
        console.log(nodes);
        //转换后，节点对象里多了一些变量
        // index：节点的索引号
        // px, py：节点上一个时刻的坐标
        // x, y：节点的当前坐标
        // weight：节点的权重
        console.log(edges);          
        //连线的变化(连线的两个节点序号，分别变成了对应的节点对象)          

        //line，线段，表示连线。        circle，圆，表示节点。              text，文字，描述节点。
        //添加连线 
        var svg_edges = svg.selectAll("line").data(edges).enter().append("line").style("stroke","#ccc").style("stroke-width",1);
        var color = d3.scale.category20();

        //添加节点 
        var svg_nodes = svg.selectAll("circle").data(nodes).enter().append("circle").attr("r",20)
            .style("fill",function(d,i){
                return color(i);
            }).call(force.drag);  //使得节点能够拖动

        //添加描述节点的文字
        var svg_texts = svg.selectAll("text").data(nodes).enter().append("text").style("fill", "black").attr("dx", 20).attr("dy", 8)
            .text(function(d){
                return d.name;
            });

        force.on("tick", function(){ //对于每一个时间间隔

        //力导向图布局 force 有一个事件 tick，每进行到一个时刻，都要调用它，更新的内容就写在它的监听器里就好
        //更新连线坐标
        svg_edges.attr("x1",function(d){ return d.source.x; })
            .attr("y1",function(d){ return d.source.y; })
            .attr("x2",function(d){ return d.target.x; })
            .attr("y2",function(d){ return d.target.y; });

        //更新节点坐标
        svg_nodes.attr("cx",function(d){ return d.x; })
            .attr("cy",function(d){ return d.y; });

        //更新文字坐标
        svg_texts.attr("x", function(d){ return d.x; })
        .attr("y", function(d){ return d.y; });
        });
    </script>
</body>
</html>